package Controlador;

import gnu.io.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.TooManyListenersException;
import Vista.Tester;

public class Conector implements SerialPortEventListener {
	private Tester _GUI = null;
	private Enumeration<?> ports = null;
	private HashMap<String, CommPortIdentifier> portMap = new HashMap<String, CommPortIdentifier>();
	private CommPortIdentifier selectedPortIdentifier = null;
	private SerialPort serialPort = null;
	private InputStream input = null;
	private OutputStream output = null;
	private boolean _CONECTADO = false;
	final static int TIMEOUT = 2000;
	final static int SPACE_ASCII = 32;
	final static int DASH_ASCII = 45;
	final static int NEW_LINE_ASCII = 10;
	String logText = "";
	private int _BAUDIOS;

	public Conector(Tester gui) {
		_GUI = gui;
	}

	public void buscarPuertos() {
		ports = CommPortIdentifier.getPortIdentifiers();
		String log = "";
		log += "Puertos Disponibles: ";

		while (ports.hasMoreElements()) {
			CommPortIdentifier curPort = (CommPortIdentifier) ports
					.nextElement();

			if (curPort.getPortType() == CommPortIdentifier.PORT_SERIAL) {
				log += curPort.getName() + " ";
				portMap.put(curPort.getName(), curPort);
				_GUI.getComboPuertos().addItem(curPort.getName());

			}
		}
		Tester.addToLog(log + "\n");
	}

	public void conectar() {
		String selectedPort = (String) _GUI.getComboPuertos().getSelectedItem();
		selectedPortIdentifier = (CommPortIdentifier) portMap.get(selectedPort);
		_BAUDIOS = (int) _GUI.getComboBaudios().getSelectedItem();
		CommPort commPort = null;

		try {
			commPort = selectedPortIdentifier
					.open("TigerControlPanel", TIMEOUT);
			serialPort = (SerialPort) commPort;
			serialPort.setSerialPortParams(_BAUDIOS, SerialPort.DATABITS_8,
					SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
			_CONECTADO = true;

			logText = selectedPort + " abierto correctamente.";
			Tester.addToLog(logText + "\n");

		} catch (PortInUseException e) {
			logText = selectedPort + " esta en uso. (" + e.toString() + ")";

			Tester.addToLog(logText + "\n");
		} catch (Exception e) {
			logText = "No se ha podido abrir " + selectedPort + "("
					+ e.toString() + ")";
			Tester.addToLog(logText + "\n");
		}
	}

	public boolean initIOStream() {
		boolean successful = false;

		try {
			input = serialPort.getInputStream();
			output = serialPort.getOutputStream();
			enviarDatos(0, "");

			successful = true;
			return successful;
		} catch (IOException e) {
			logText = "I/O Streams failed to open. (" + e.toString() + ")";
			Tester.addToLog(logText + "\n");
			return successful;
		}
	}
	
	public void initListener() {
		try {
			serialPort.addEventListener(this);
			serialPort.notifyOnDataAvailable(true);
		} catch (TooManyListenersException e) {
			logText = "Demasiados listeners. (" + e.toString() + ")";
			Tester.addToLog(logText + "\n");
		}
	}

	public void desconectar() {
		try {
			enviarDatos(0, "");

			serialPort.removeEventListener();
			serialPort.close();
			input.close();
			output.close();
			_CONECTADO = false;

			logText = "Desconectado.";
			Tester.addToLog(logText + "\n");
		} catch (Exception e) {
			logText = "Failed to close " + serialPort.getName() + "("
					+ e.toString() + ")";
			Tester.addToLog(logText + "\n");
		}
	}

	final public boolean estaConectado() {
		return _CONECTADO;
	}

	public void serialEvent(SerialPortEvent evt) {
		if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
			try {
				byte singleData = (byte) input.read();

				if (singleData != NEW_LINE_ASCII) {
					logText = new String(new byte[] { singleData });
					Tester.addToLog(logText);
				} else {
					Tester.addToLog("\n");
				}
			} catch (Exception e) {
				logText = "No se han podido leer datos. (" + e.toString() + ")";
				Tester.addToLog(logText + "\n");
			}
		}
	}

	public void enviarDatos(int dato, String sensor) {
		try {
			switch (sensor) {
			case "temperatura":
				output.write(1);

				break;

			case "humedad":
				output.write(2);

				break;

			case "presion":
				output.write(3);

				break;
			default:
				output.write(3);

				break;
			}
			output.flush();
			output.write(DASH_ASCII);
			output.flush();
			output.write(dato);
			output.flush();

			Tester.addToLog(sensor + "-" + dato + "\n");

		} catch (Exception e) {
			Tester.addToLog("No se han podido escribir datos. (" + e.toString()
					+ ")");
		}
	}
}